#pragma GCC optimize(2) //开启O2优化
#if 0
#include<iostream>
#include<cmath>
using namespace std;
// 补：算法一般在 10^7 ~10^8 可以1秒算出来
typedef long long ll;
/*
 git:
 git add
 git commit -m “注释”
 git push -u origin master
*/

// const int N = 110;
// double g[N][N];
// int n;
// const double eps = 1e-7;

// void swap(int i, int j)
// {
//     double tmp[n + 1];
//     memcpy(tmp, g[i], sizeof tmp);
//     memcpy(g[i], g[j], sizeof tmp);
//     memcpy(g[j], tmp, sizeof tmp);
// }

// // 第i行 *k 加到第j行
// void add(int i, int j, double k)
// {
//     for (int col = 0; col <= n; ++col)
//         g[j][col] += g[i][col] * k;
// }

// void mul(int i, double k)
// {
//     for (int j = 0; j <= n; ++j)
//         g[i][j] *= k;
// }

// int main()
// {
//     scanf("%d", &n);
//     for (int i = 0; i < n; ++i)
//         for (int j = 0; j <= n; ++j)
//             scanf("%lf", &g[i][j]);

//     int r = 0, c = 0;
//     while (c < n)
//     {
//         int t = r;
//         for (int i = r + 1; i < n; ++i)
//             if (fabs(g[i][c]) > fabs(g[t][c]))
//                 t = i;
//         if (fabs(g[t][c]) < eps)
//         {
//             ++c;
//             continue;
//         }
//         mul(t, 1.0 / g[t][c]);
//         swap(t, r);
//         for (int i = r + 1; i < n; ++i)
//             if (fabs(g[i][c]) > eps)
//                 add(r, i, -g[i][c]);
//         ++c, ++r;
//     }
//     if (r < n)
//     {
//         for (int i = r; i < n; ++i)
//             if (fabs(g[i][n]) > eps)
//             {
//                 puts("No solution");
//                 return 0;
//             }
//         puts("Infinite group solutions");
//     }
//     else
//     {
//         for (int i = n - 1; i >= 0; --i)
//         {
//             for (int j = i - 1; j >= 0; --j)
//                 add(i, j, -g[j][i]);
//         }
//         for (int i = 0; i < n; ++i)
//             printf("%.2lf\n", g[i][n]);
//     }
//     return 0;
// }

/************************ 组合数 *************************/
// 1、a和b的数据范围较小，Cab = C(a-1)b + C(a-1)(b-1), dp预处理
// https://www.acwing.com/problem/content/887/

// typedef long long ll;
// const int N = 2010;
// int dp[N][N]; //dp[i][j]: Ci j
// const int mod = 1e9 + 7;
// int main()
// {
//     for(int i = 0; i < N; ++i)
//         dp[i][0] = 1;
//     for(int i = 1; i < N; ++i)
//         for(int j = 1; j < N; ++j)
//             dp[i][j] = ((ll)dp[i - 1][j] + dp[i - 1][j - 1]) % mod;
//             // dp[i][j] = (ll)dp[i - 1][j] + dp[i - 1][j - 1] % mod;  注：% 优先级比 + 高
//     int n;
//     scanf("%d", &n);
//     int a, b;
//     while(n--)
//     {
//         scanf("%d %d", &a, &b);
//         printf("%d\n", dp[a][b]);
//     }
//     return 0;
// }

// 2、a和b范围稍微有点大 1 ~ 10^6
// Cab = a! / (b! * (a-b)!)
// 可以预处理处理10^6 范围内的所有阶乘，而由于 (a / b) % m != (a % m) / (b % m)
// 就要用逆元 (a / b) % m = (a * b^-1) % m, 根据定义可知 1 的逆元还是 1
/*
const int N = 1e5 + 10, mod = 1e9 + 7;  // mod为质数，可以用快速幂求逆元
int fac[N], inv[N]; // fac[i]表示 i的阶乘，inv[i]表示i的阶乘的逆元

void init()
{
    for(int i = 1; i < N; ++i)
    {
        fac[i] = (ll)i * fac[i - 1] % mod;  // i! = (i - 1)! * i
        inv[i] = qmi(fac[i], mod - 2, mod); // (i!)^-1 = (i!)^(mod - 2) % mod
        // inv[i] = (ll)inv[mod % i] * (mod - mod / i) % mod; //这一步求的是i的逆元，而非i!的逆元
    }
}
int main()
{
    printf("%d\n", 5 + 7 % 5);
    printf("%d\n", (5 + 7) % 5);
    return 0;
}*/

// 3、a和b范围很大，但是模数p的范围较小。借助卢卡斯定理
/*
const int N = 1e5 + 10;
int fac[N];
int inv[N];

int qmi(int a, int b, int p)
{
    int ret = 1;
    for (; b; b >>= 1, a = (ll)a * a % p)
        if (b & 1)
            ret = (ll)ret * a % p;
    return ret;
}

void init(int p)
{
    fac[0] = inv[0] = 1;
    for (int i = 1; i < p; ++i)
    {
        fac[i] = (ll)i * fac[i - 1] % p;
        inv[i] = qmi(fac[i], p - 2, p);
    }
}

int p;
// ll cal(ll a, ll b)
// {
//     if(!b)  return 1;
//     int a1 = a % p, b1 = b % p;
//     ll t = ((ll)fac[a1] * inv[b1] % p) * inv[a1 - b1] % p;
//     return t * cal(a / p, b / p) % p;
// }

// 计算Cab，迭代版
ll cal(ll a, ll b)
{
    ll ret = 1;
    while (b)
    {
        int a1 = a % p, b1 = b % p;
        ll t = ((ll)fac[a1] * inv[b1] % p) * inv[a1 - b1] % p;
        ret = ret * t % p;
        a /= p, b /= p;
    }
    return ret;
}

int main()
{
    int n;
    scanf("%d", &n);
    ll a, b;

    while (n--)
    {
        scanf("%lld %lld %d", &a, &b, &p);
        init(p);
        printf("%lld\n", cal(a, b));
    }
    return 0;
}*/

// 4、高精度 求Cab （分解质因数 + 高精度乘法）
// 分解质因数 + 高精度乘法
#include <iostream>
using namespace std;
#include <unordered_map>

typedef long long ll;
int a, b;
unordered_map<int, int> ha;

void div(int n, bool flag) // flag 表示n 是否在分子
{
    for (int i = 2; i <= n / i; ++i)
    {
        if (n % i == 0)
        {
            int c = 0;
            while (n % i == 0)
            {
                n /= i;
                ++c;
            }
            if (flag)  ha[i] += c;
            else       ha[i] -= c;
        }
    }
    if (n > 1)
    {
        if (flag) ha[n]++;
        else      ha[n]--;
    }
}

// 筛选出 <= a 的所有质数
int primes[5000], idx;
bool st[5010];
void euler(int n)
{
    for (int i = 2; i <= n; ++i)
    {
        if (!st[i])
            primes[idx++] = i;
        for (int j = 0; primes[j] <= n / i; ++j)
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
                break;
        }
    }
}

// 求n!的质因数p的指数 = n/p + n/p^2 + n/p^3 + ...
int get(int n, int p)
{
    int t = p, ret = 0;
    while (n / t)
    {
        ret += n / t;
        t *= p;
    }
    return ret;
}

// // 求n!的质因数p的指数 另一种暴力方法。此方法效率不如上面的
// int get(int n, int p)
// {
//     int cnt = 0;
//     for (int i = 2; i <= n; ++i)
//     {
//         if (i % p == 0)
//         {
//             int n = i;
//             while (n % p == 0)
//             {
//                 ++cnt;
//                 n /= p;
//             }
//         }
//     }
//     return cnt;
// }

int ans[100000], len;
void mul(int k) // ans *= k
{
    int next = 0;
    int i = 0;
    for (; i < len || next; ++i)
    {
        next += ans[i] * k;
        ans[i] = next % 10;
        next /= 10;
    }
    len = i;
}

// 法一：逐个分解质因数 (分解 1 ~ b 和 a ~ a-b+1 中的所有数的质因数)
void test01()
{
    cin >> a >> b;
    // 分解a ~ a-b+1 所有数的质因数，放到ha
    for (int i = a; i > a - b; --i)
        div(i, true);
    // 分解2 ~ b 所有数的质因数
    for (int i = 2; i <= b; ++i)
        div(i, false);
    // 高精度乘法
    ans[0] = 1, len = 1;
    for (auto [p, a] : ha)
    {
        while (a)
        {
            mul(p);
            --a;
        }
    }
    for (int i = len - 1; i >= 0; --i)
        printf("%d", ans[i]);
}

// 法二：计算出 a!中 p1的个数、p2的个数、...
void test02()
{
    cin >> a >> b;
    euler(a);
    for (int j = 0; j < idx; ++j)
    {
        int p = primes[j];
        int k = get(a, p) - get(b, p) - get(a - b, p);
        if (k)
            ha[p] = k;
    }

    ans[0] = 1, len = 1;
    for (auto [p, a] : ha)
    {
        while (a)
        {
            mul(p);
            --a;
        }
    }
    for (int i = len - 1; i >= 0; --i)
        printf("%d", ans[i]);
}

int main()
{
    test02();
    return 0;
}

#endif
